﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Xml.Serialization;
using System.IO;

namespace YasharEl.Infrastructure.ServiceModel.Messaging
{
    public class MessageHeaderInformationAttacher : IClientMessageInspector, IEndpointBehavior
    {
        #region Fields

        private readonly List<MessageHeaderProviderInformation> messageHeaderEntries = new List<MessageHeaderProviderInformation>();

        #endregion

        #region Constructors

        public MessageHeaderInformationAttacher(List<MessageHeaderProviderInformation> entries)
        {
            if (entries != null)
            {
                messageHeaderEntries = entries;
            }
        }

        #endregion

        #region IClientMessageInspector Implementations

        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
        }

        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            // TODO : Validate all possible problems and throw exception for each case
            if (request != null)
            {
                foreach (MessageHeaderProviderInformation messageHeaderEntry in messageHeaderEntries)
                {
                    MessageHeaderValueWrapper valueWrapper = new MessageHeaderValueWrapper();
                    valueWrapper.RealValue = messageHeaderEntry.ValueProvider.ProvideValue();

                    XmlSerializer serializer = new XmlSerializer(typeof(MessageHeaderValueWrapper));

                    StringWriter textWriter = new StringWriter();
                    serializer.Serialize(textWriter, valueWrapper);

                    string text = textWriter.ToString();

                    MessageHeader messageHeader = MessageHeader.CreateHeader(
                        messageHeaderEntry.MessageHeaderKey, 
                        messageHeaderEntry.MessageHeaderNamespace,
                        text
                    );

                    request.Headers.Add(messageHeader);

                    textWriter.Close();
                }
            }

            return null;
        }

        #endregion

        #region IEndpointBehavior Implementations

        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(this);
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
        }

        public void Validate(ServiceEndpoint endpoint)
        {
        }

        #endregion
    }
}
